# @rspress/plugin-playground <SourceCode href="https://github.com/web-infra-dev/rspress/tree/main/packages/plugin-playground" />

import { SourceCode, PackageManagerTabs } from '@rspress/core/theme';

Provide a real-time playground to preview the code blocks in MDX files.

## Installation

<PackageManagerTabs command="add @rspress/plugin-playground -D" />

## Usage

### Register

First, write the following config in the config file:

```ts title="rspress.config.ts"
import { defineConfig } from '@rspress/core';
import { pluginPlayground } from '@rspress/plugin-playground';

export default defineConfig({
  plugins: [pluginPlayground()],
});
```

:::warning Note

This plugin will set `markdown.mdxRs` to `false`. In the future, the Rspress team will port this plugin to the Rust version of the compiler.

:::

### Internal components

:::tip Note
It is recommended to use js or jsx to write sample code to avoid ts type errors in the editor.
:::

The component code of internal components is declared in the mdx file. This plugin supports jsx and tsx. You can declare the following code block in the mdx file:

````mdx
```jsx
import React from 'react';

function App() {
  return <div>Hello World</div>;
}

export default App;
```
````

Otherwise, You can use `direction` parameter to specify the playground layout, `horizontal` and `vertical` are supported:

````mdx
```jsx direction=vertical
import React from 'react';

function App() {
  return <div>Hello World</div>;
}

export default App;
```
````

It's worth noting that you need to export the component as default, and Rspress will automatically render this component.

But if you want to keep the style of the code block instead of rendering it as a component, you can add the `pure` identifier to specify, the usage is as follows:

````mdx
```tsx pure
import React from 'react';

function App() {
  return <div>Hello World</div>;
}

export default App;
```
````

If you have set `defaultRenderMode` to `'pure'`, Rspress will not render this component by default, but instead display it as a code block. If you want to render a code block as a component in this situation, you can do add the `preview` identifier to specify, the usage is as follows:

````mdx
```tsx playground
function App() {
  return <div>Hello World</div>;
}
export default App;
```
````

:::tip Tip
Make sure the document ends with `.mdx`.
:::

### External components

In addition to writing component code in the code block of the mdx file, you can also write component code in an external file and then import it in the mdx file through the meta tag of `file="./filename"`. For example

````md title="example.mdx"
```jsx file="./Demo.jsx"

```
````

```jsx title="Demo.jsx"
import React from 'react';

export default function App() {
  return <div>Hello World</div>;
}
```

Same as internal components, external components also support `direction` attribute:

````md title="example.mdx"
```jsx file="./Demo.jsx" direction=vertical

```
````

External components also need to export the component as default. Through the src attribute of the code tag, you can specify the path of the external component. This plugin supports both relative paths and alias paths(alias).

For some more complex components, this way of using external components will be more convenient.

### Define the layout of the entire page

You can write `playgroundDirection` in frontmatter to define the layout of the editor and preview area in the entire page.

```md title="example.mdx"
---
title: title
playgroundDirection: horizontal
---
```

Priority: Defined directly on the preview area > Page Definition > Configuration.

## Configuration

This plugin accepts an object parameter, the type is as follows:

```ts
interface PlaygroundOptions {
  render: string;
  include: Array<string | [string, string]>;
  // Define the default playground layout (horizontal/vertical)
  defaultDirection: 'horizontal' | 'vertical';
  // Define the position of the editor in horizontal layout (left/right)
  editorPosition: 'left' | 'right';
  // Default editor (monaco) partial configuration
  monacoLoader: Parameters<typeof loader.config>[0];
  monacoOptions: MonacoEditorProps['options'];
}
```

:::warning Note

`monacoLoader` and `monacoOptions` will be serialized to JSON, so some data types, such as functions and circularly referenced objects, are not supported.

:::

### render

You can customize the render file for rendering Playground. Please note that the file name must be `Playground.(jsx?|tsx?)`

```ts
pluginPlayground({
  render: '/path/to/render/Playground.tsx',
});
```

In the custom playground, you can directly import the original editor and renderer, and import pre-packaged dependencies through `_rspress_playground_imports`:

```ts
import getImport from '_rspress_playground_imports';
import { Runner, Editor } from '@rspress/plugin-playground/web';
```

You can refer to the built-in [Playground.tsx](https://github.com/web-infra-dev/rspress/tree/main/packages/plugin-playground/static/global-components/Playground.tsx).

### include

By default, this plugin will automatically scan all import statements in the demos, the packages not used in the demos cannot be used in the playground. If you want to add other packages to the playground, you can use the `include` parameter:

```ts
pluginPlayground({
  include: [
    // Add dayjs package
    'dayjs',
    // Add a package named "my-package", and it actual reference to "/path/to/package/index.js"
    ['my-package', '/path/to/package/index.js'],
  ],
});
```

### babelUrl

Playground uses `@babel/standalone` to compile the demo code, loaded from [cdnjs.com](https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.22.20/babel.min.js) by default.

You can modify the URL served to other CDNs, such as unpkg, jsdelivr, etc.

### monacoLoader

Configure monaco-loader behaviors, loaded from [cdnjs.com](https://cdnjs.com/libraries/monaco-editor) by default.

You can modify the URL served to other CDNs, such as unpkg, jsdelivr, etc.

The full document can be found at [suren-atoyan/monaco-loader](https://github.com/suren-atoyan/monaco-loader#config)

### monacoOptions

Configure monaco editor, corresponding to [IStandaloneEditorConstructionOptions](https://microsoft.github.io/monaco-editor/typedoc/interfaces/editor.IStandaloneEditorConstructionOptions.html)

### defaultRenderMode

The default mode of rendering internal code blocks that do not have the `pure` or `playground` identifiers declared by users, defaulting to `playground`.

- `pure`: render as regular code block
- `playground`: render as Playground component
